package com.agen.basenet.util

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkRequest
import android.os.Handler
import android.os.Looper
import android.util.Log
import java.util.concurrent.CopyOnWriteArrayList

object ConnectManager {

    private const val TAG = "ConnectManager"
    private val mainHandler = Handler(Looper.getMainLooper())

    private var availableNetWorks: MutableList<Network> = mutableListOf()

    private val networkCallbacks = CopyOnWriteArrayList<Callback>()

    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            availableNetWorks.add(network)
            if (availableNetWorks.size == 1) {
                Log.i(TAG, "net onAvailable")
                networkCallbacks.forEach {
                    mainHandler.post {
                        it.onAvailable()
                    }
                }
            }
        }

        override fun onLost(network: Network) {
            super.onLost(network)
            availableNetWorks.remove(network)
            if (availableNetWorks.isEmpty()) {
                Log.i(TAG, "net onUnavailable")
                networkCallbacks.forEach {
                    mainHandler.post {
                        it.onUnavailable()
                    }
                }
            }
        }
    }

    fun init(context: Context) {
        val cm: ConnectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val nrBuilder = NetworkRequest.Builder()
        cm.registerNetworkCallback(nrBuilder.build(), networkCallback)
    }

    fun isConnected(): Boolean {
        return availableNetWorks.isNotEmpty()
    }

    fun registerNetworkCallback(callback: Callback) {
        networkCallbacks.add(callback)
        if (Thread.currentThread() == Looper.getMainLooper().thread) {
            if (isConnected()) {
                callback.onAvailable()
            } else {
                callback.onUnavailable()
            }
        } else {
            mainHandler.post {
                if (isConnected()) {
                    callback.onAvailable()
                } else {
                    callback.onUnavailable()
                }
            }
        }

    }

    fun unregisterNetworkCallback(callback: Callback) {
        networkCallbacks.remove(callback)
    }

    interface Callback {
        fun onAvailable() {}
        fun onUnavailable() {}
    }
}